home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
CUGUK
/
COMMS
/
C101.ZIP
/
UUPC11XS.ZIP
/
MAIL
/
RMAIL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-05
|
40KB
|
994 lines
/*--------------------------------------------------------------------*/
/* r m a i l . c */
/* */
/* Delivery agent for UUPC/extended */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* Changes Copyright (c) 1989 by Andrew H. Derbyshire. */
/* */
/* Changes Copyright (c) 1990-1992 by Kendra Electronic */
/* Wonderworks. */
/* */
/* All rights reserved except those explicitly granted by the */
/* UUPC/extended license agreement. */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* RCS Information */
/*--------------------------------------------------------------------*/
/*
* $Id: RMAIL.C 1.5 1992/12/05 23:38:43 ahd Exp $
*
* $Log: RMAIL.C $
* Revision 1.5 1992/12/05 23:38:43 ahd
* Let logger close the log, not rmail
*
* Revision 1.4 1992/12/04 01:00:27 ahd
* Add copyright messages
*
*/
/*--------------------------------------------------------------------*/
/* Function: Stand alone mail delivery module for */
/* UUPC/extended */
/* Language: Borland C++ 3.1 (ANSI C mode) or Microsoft C 6.0. */
/* Arguments: One or more addresses to deliver mail to */
/* or "-t" to direct rmail to read the addresses */
/* from the RFC-822 header. */
/* A third mode of operation is to specify '-w' and/ */
/* or '-s subject' followed by one or more addresses */
/* with optional carbon copy flags (-c or -b) before */
/* additional addresses. This causes rmail to */
/* function like a bare bones batch version of the */
/* MAIL program; a valid RFC-822 header is generated */
/* and the mail is delivered, aliases are not expanded */
/* and the mail is not locally logged. (The current */
/* user id as the from address is used unless the */
/* environment variable LOGNAME is set, in which case */
/* it is used.) */
/* Optional argument "-f" to denote file to read in */
/* place of stdin. */
/* Optional argument "-F" to denote file to read in */
/* place of stdin and DELETE after readering. */
/* Optional argument "-x" to for debug level */
/* Input: mail to be delivered, with RFC-822 header, on */
/* stdin. */
/* Output: 'From' and 'Received:' headers are added, */
/* 'Bcc:' headers are removed, and the mail is */
/* delivered to one or more local users and/or */
/* one or more remote users. */
/* Exit code: 0 Success */
/* 1 One or more letters not delivered */
/* 2 No mail delivered */
/* 3 Configuration file error */
/* 4 Invalid option/help specified */
/* 5 Invalid option/help specified */
/* */
/* Note: When parsing RFC-822 headers, this program */
/* expects them to be "well-behaved", that is in */
/* format generated by UUPC/extended. This implies: */
/* */
/* One address per line */
/* */
/* Resent- headers, if any, before the original */
/* headers. */
/* */
/* From: header must precede To: header. */
/* */
/* To: header must precede Cc: and Bcc: headers. */
/* */
/* Cc: and Bcc: headers must be together (one */
/* after the other) */
/* */
/* The MUA has prefixed any obsolete Resent- */
/* headers by X- */
/* */
/* Note: The "-t" flag is supported by BSD sendmail for the */
/* purpose listed above, but we also turn use it to */
/* control other special options, all of which */
/* basically cause the program to act more like a */
/* local mailer than a remote mailer; these options */
/* include: */
/* */
/* Stripping off blind carbon copies */
/* */
/* Generating the UUCP From line differently */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* System include files */
/*--------------------------------------------------------------------*/
#include <stdio.h>
#include <ctype.h>
#include <io.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <signal.h>
/*--------------------------------------------------------------------*/
/* Application include files */
/*--------------------------------------------------------------------*/
#include "lib.h"
#include "address.h"
#include "arpadate.h"
#include "deliver.h"
#include "getopt.h"
#include "hlib.h"
#include "hostable.h"
#include "logger.h"
#include "security.h"
#include "usertabl.h"
#include "timestmp.h"
#include "catcher.h"
/*--------------------------------------------------------------------*/
/* Local defines */
/*--------------------------------------------------------------------*/
#define MOPLEN 10 /* Length of formatted header lines */
#define UUCPFROM "From " /* Length of UUCP incoming mail */
/*--------------------------------------------------------------------*/
/* Prototypes for internal files */
/*--------------------------------------------------------------------*/
static boolean CopyTemp( void );
static void ParseFrom( void );
static char **Parse822( boolean *header,
size_t *count);
static void Terminate( const int rc);
static void PutHead( const char *label,
const char *operand,
FILE *stream,
const boolean resent);
static boolean DaemonMail( const char *subject,
char **address,
int count );
static void usage( void );
/*--------------------------------------------------------------------*/
/* Global variables */
/*--------------------------------------------------------------------*/
currentfile(); /* Declare file name for checkref() */
char *tempname = NULL; /* Pointer to temporary input file */
char *namein = CONSOLE;
FILE *datain = stdin; /* Handle for reading input mail */
FILE *dataout = NULL; /* Handle for the output of mail */
char fromuser[MAXADDR] = ""; /* User id of originator */
char fromnode[MAXADDR] = ""; /* Node id of originator */
char *now; /* Time stamp for Received: banner */
static char received[] = "Received:";
static char receivedlen = sizeof( received) - 1;
/*--------------------------------------------------------------------*/
/* main program */
/*--------------------------------------------------------------------*/
void main(int argc, char **argv)
{
boolean ReadHeader = FALSE; /* TRUE = Parse RFC-822 headers */
int option; /* For parsing option list */
char **address; /* Pointer to list of target
addresses */
char *token;
size_t addressees; /* Number of targets in address */
size_t count; /* Loop variable for delivery */
size_t delivered = 0; /* Count of successfull deliveries */
boolean header = TRUE;
boolean DeleteInput = FALSE;
boolean daemon = FALSE;
char *subject = NULL;
/*--------------------------------------------------------------------*/
/* Make a copy of the Borland copyright for debugging purposes */
/*--------------------------------------------------------------------*/
#if defined(__CORE__)
copywrong = strdup(copyright);
checkref(copywrong);
#endif
banner( argv);
now = arpadate(); /* Set the current date */
debuglevel = -1; /* Set default so we can detect it */
/*--------------------------------------------------------------------*/
/* Load the UUPC/extended configuration file, and exit if any errors */
/*--------------------------------------------------------------------*/
if (!configure(B_MTA))
Terminate(3);
/*--------------------------------------------------------------------*/
/* Handle control-C interrupts */
/*--------------------------------------------------------------------*/
if( signal( SIGINT, ctrlchandler ) == SIG_ERR )
{
printmsg( 0, "Couldn't set SIGINT\n" );
panic();
}
/*--------------------------------------------------------------------*/
/* Begin logging messages */
/*--------------------------------------------------------------------*/
openlog( NULL );
/*--------------------------------------------------------------------*/
/* Parse our operand flags */
/*--------------------------------------------------------------------*/
while ((option = getopt(argc, argv, "ws:tF:f:x:")) != EOF)
{
switch (option) {
case 'w':
daemon = TRUE;
break;
case 's':
subject = optarg;
daemon = TRUE;
break;
case 't':
ReadHeader = TRUE;
break;
case 'x':
debuglevel = atoi(optarg);
break;
case 'F':
DeleteInput = TRUE;
case 'f':
namein = optarg;
datain = FOPEN(namein , "r", TEXT);
break;
case '?':
usage();
Terminate(4);
} /* switch */
} /* while */
if ( debuglevel > 1 )
{
for ( count = 1; (int) count < argc; count ++)
printmsg(4,"rmail argv[%d] = \"%s\"", count, argv[count] );
} /* if ( debuglevel > 4 ) */
if ((optind == argc) != ReadHeader)
{
puts("Missing/extra parameter(s) at end.");
Terminate(4);
}
remoteMail = ! (ReadHeader || daemon);
/* If not reading headers, must be in
normal rmail mode ... */
/*--------------------------------------------------------------------*/
/* If in local mode and the user doesn't want output, suppress */
/* routine delivery messages */
/*--------------------------------------------------------------------*/
if ( debuglevel == -1 )
{
if (remoteMail)
debuglevel = 1;
else
debuglevel = (int) bflag[F_VERBOSE];
}
/*--------------------------------------------------------------------*/
/* Verify we have input stream available */
/*--------------------------------------------------------------------*/
if (datain == NULL )
{
printerr(namein);
Terminate(3);
} /* if */
/*--------------------------------------------------------------------*/
/* Open up the output data stream */
/*--------------------------------------------------------------------*/
tempname = mktempname( NULL , "TMP");
dataout = FOPEN(tempname, "w", TEXT);
if (dataout == NULL)
{
printmsg(0,"Cannot open temporary file \"%s\" for output",
tempname);
Terminate(5);
} /* if */
/*--------------------------------------------------------------------*/
/* If in local mail mode, make up a list of addresses to mail to */
/*--------------------------------------------------------------------*/
if ( daemon )
{
addressees = argc - optind;
address = &argv[optind];
DaemonMail( subject, address, addressees );
header = FALSE;
}
else if (ReadHeader)
address = Parse822( &header, &addressees );
else {
ParseFrom(); /* Copy remote header instead */
addressees = argc - optind;
address = &argv[optind];
} /* if */
if ( addressees == 0 ) /* Can we deliver mail? */
{
printmsg(0, "No addressees to deliver to!");
Terminate( 2 ); /* No --> Execute punt formation */
}
/*--------------------------------------------------------------------*/
/* Copy the rest of the input file into our holding tank */
/*--------------------------------------------------------------------*/
header = CopyTemp( ) && header ;
if (header) /* Was the header ever terminated? */
{
printmsg(0,"rmail: Improper header, adding trailing newline");
fputc('\n', dataout); /* If not, it is now ... */
}
fclose(datain);
fclose(dataout);
if (DeleteInput) /* Make room for more data on disk */
remove(namein);
/*--------------------------------------------------------------------*/
/* Determine requestor node and user id for remote mail */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* Perform delivery of the mail */
/*--------------------------------------------------------------------*/
while ((token = strpbrk(tempname ,"/")) != NULL)
*token = '\\';
for ( count = 0; count < addressees; count++)
if ( *address[count] == '-')
delivered ++; /* Ignore option flags on delivery */
else
delivered += Deliver(tempname, address[count], FALSE, TRUE);
/*--------------------------------------------------------------------*/
/* Terminate the program */
/*--------------------------------------------------------------------*/
printmsg(8,"rmail: %d addressees, delivered to %d mailboxes",
addressees, delivered);
if ( delivered >= addressees )
Terminate( 0 ); /* All mail delivered */
else if ( delivered == 0 )
Terminate( 2 ); /* No mail delivered */
else
Terminate (1 ); /* Some mail delivered */
} /* main */
/*--------------------------------------------------------------------*/
/* T e r m i n a t e */
/* */
/* Cleanup open files and return to operating system */
/*--------------------------------------------------------------------*/
static void Terminate( const int rc)
{
if (tempname != NULL) /* Did temporary file get named? */
{
if (datain != stdin) /* Non-standard input? */
fclose(stdin); /* Yes --> Close it */
remove(tempname); /* Purge temporary file, if exists */
} /* if */
exit( rc ); /* Return to operating systems */
} /* Terminate */
/*--------------------------------------------------------------------*/
/* P a r s e F r o m */
/* */
/* Read the from address of incoming data from UUCP */
/*--------------------------------------------------------------------*/
static void ParseFrom()
{
static char from[] = "From ";
static char remote[] = "remote from ";
static int remotelen = sizeof remote - 1;
static int fromlen = sizeof from - 1;
char *token;
char buf[BUFSIZ];
boolean hit;
/*--------------------------------------------------------------------*/
/* Use UUXQT Information, if available */
/*--------------------------------------------------------------------*/
token = getenv( UU_MACHINE );
if ( token == NULL )
*fromnode = '\0';
else {
strncpy( fromnode, token , sizeof fromnode );
fromnode[ sizeof fromnode - 1 ] = '\0';
}
fgets(buf, BUFSIZ , datain);
hit = equaln(buf, from, fromlen );
if (hit)
{
int nodelen = strlen( fromnode ) + 1; /* Plus ! */
char *s;
token = strtok( &buf[ fromlen ], " ");
s = strtok( NULL, "\n");
if (strlen( token ) + nodelen >= MAXADDR)
{
char *next;
token = strtok( token, "!" );
while ((next = strtok( NULL , "!")) != NULL )
{
token = next;
if (strlen( next ) + nodelen < MAXADDR)
break;
} /* while */
} /* if */
strncpy(fromuser, token , sizeof fromuser );
fromuser[ sizeof fromuser - nodelen ] = '\0';
if ( *fromnode == '\0')
{
while ( *s != '\0')
{
if equaln(s, remote, remotelen)
break;
else
s++;
} /* while */
strncpy( fromnode ,
(*s == '\0') ? E_nodename : s + remotelen ,
sizeof fromnode );
fromnode[ sizeof fromnode -1 ] = '\0';
} /* if ( *fromnode != '\0') */
} /* if */
else {
if ( *fromnode == '\0')
strcpy(fromnode, E_nodename );
strcpy(fromuser, "/dev/null");
} /* else */
/*--------------------------------------------------------------------*/
/* Generate required "From " and "Received" header lines */
/*--------------------------------------------------------------------*/
fprintf(dataout,"%-10s from %s by %s (%s %s) with UUCP;\n%-10s %s\n",
"Received:", fromnode, E_domain, compilep, compilev,
" ", now);
/*--------------------------------------------------------------------*/
/* If what we read wasn't a From line, write into the new file */
/*--------------------------------------------------------------------*/
if (!hit)
{
fputs(buf, dataout);
if (ferror(dataout))
{
printerr(tempname);
Terminate(3);
} /* if */
} /* if */
/*--------------------------------------------------------------------*/
/* Determine the requestor user id and node */
/*--------------------------------------------------------------------*/
token = getenv( UU_USER ); /* Get exactly what remote told us */
if ( token != NULL )
{ /* Use exactly what remote told us */
ruser = strtok( token , WHITESPACE );
rnode = strtok( NULL , WHITESPACE );
} /* else */
if ((rnode == NULL) || (strchr(rnode,'.') == NULL ))
/* Did it tell us the domain? */
{ /* No --> Use from information */
char node[MAXADDR];
char user[MAXADDR];
sprintf(buf ,"%s!%s", fromnode, fromuser);
user_at_node(buf , buf, node, user);
ruser = newstr( user );
rnode = newstr( node );
}
uuser = "uucp"; /* Effective id is always our daemon */
} /* ParseFrom */
/*--------------------------------------------------------------------*/
/* P a r s e 8 2 2 */
/* */
/* Parse an RFC-822 header generated by that esteemed mail user */
/* agent, UUPC/extended's MAIL. */
/* */
/* Note that we parse the header in the format we KNOW that UUPC */
/* generated it in: "To:", "Cc:", "Bcc:", optionally prefixed */
/* by "Resent-". We also know that mail comes in one address */
/* per line, and that the Resent- headers, if any, precede the */
/* original headers. */
/*--------------------------------------------------------------------*/
static char **Parse822( boolean *header,
size_t *count)
{
/*--------------------------------------------------------------------*/
/* Define the headers we will be examining and variables for their */
/* lengths */
/*--------------------------------------------------------------------*/
static char *to = "Resent-To:";
static char *cc = "Resent-Cc:";
static char *bcc = "Resent-Bcc:";
static char *resent = "Resent-";
static char *from = "Resent-From:";
size_t tolen;
size_t cclen;
size_t bcclen;
size_t resentlen = strlen(resent);
size_t offset = resentlen; /* Subscript for examining headers,
which allows us to ignore Resent- */
size_t fromlen = strlen( &from[offset] );
size_t allocated = 5; /* Reasonable first size for address */
/* Note: MUST BE AT LEAST 2 because we
add 50% below! */
boolean blind = FALSE;
char **addrlist = calloc( sizeof *addrlist , allocated);
char buf[BUFSIZ]; /* Input buffer for reading header */
char address[MAXADDR]; /* Buffer for parsed address */
char path[MAXADDR];
char *token; /* For parsing line in buf */
struct HostTable *hostp;
/*--------------------------------------------------------------------*/
/* Begin processing */
/*--------------------------------------------------------------------*/
*count = 0; /* No addresses discovered yet */
checkref(addrlist); /* Verify we had room for the list */
fprintf(dataout,"%-10s by %s (%s %s);\n%-10s %s\n",
"Received:",E_domain,compilep, compilev,
" ", now );
/*--------------------------------------------------------------------*/
/* Find the From: line */
/*--------------------------------------------------------------------*/
do {
if (fgets( buf, BUFSIZ, datain) == NULL) /* End of file? */
return NULL; /* Yes --> Very bad, report error */
fputs(buf, dataout );
if (*buf == '\n') /* End of the header? */
return NULL; /* Yes --> Very bad, report error */
else if (equalni(resent, buf, resentlen))
{
offset = 0;
fromlen = strlen(&from[offset]);
} /* if */
else if (equalni(received, buf, receivedlen))
hops++;
} while (!equalni(&from[offset], buf, fromlen));
strtok( buf , WHITESPACE); /* Drop the leading token */
token = strtok( NULL, "\n"); /* Get the token with From: addr */
ExtractAddress( address, token, FALSE );
/* Get the From: address itself */
user_at_node(address, path, fromnode, fromuser);
/* Separate portions of the address */
/*--------------------------------------------------------------------*/
/* Generate a Sender: line if we need it */
/*--------------------------------------------------------------------*/
if (equal(fromnode,HostAlias(E_fdomain))) /* Same as hidden site? */
strcpy(fromnode, E_nodename);/* Yes --> Declare as local system */
hostp = checkname( fromnode ); /* Look up real system name */
if (!equal(fromuser,E_mailbox) ||
(hostp == BADHOST) || (hostp->hstatus != localhost))
{
sprintf(buf, "%s <%s@%s>", E_name, E_mailbox, E_fdomain );
PutHead("Sender:", buf, dataout , offset == 0 );
} /* if */
/*--------------------------------------------------------------------*/
/* Set UUCP requestor name while we've got the information */
/*--------------------------------------------------------------------*/
if ((hostp != BADHOST) && (hostp->hstatus == localhost))
rnode = bflag[F_BANG] ? E_nodename : E_fdomain;
/* Use full domain address, if possible */
else
rnode = fromnode;
uuser = ruser = fromuser; /* User and requestor always the same
for locally generated mail */
/*--------------------------------------------------------------------*/
/* Generate a message-id */
/*--------------------------------------------------------------------*/
sprintf(buf, "<%lx.%s@%s>", time( NULL ) , E_nodename, E_domain);
PutHead("Message-ID:", buf, dataout , offset == 0 );
PutHead(NULL, NULL, dataout , FALSE );
/*--------------------------------------------------------------------*/
/* Locate the To: or Resent-To: line */
/*--------------------------------------------------------------------*/
tolen = strlen( &to[offset] );
do {
if (fgets( buf, BUFSIZ, datain ) == NULL) /* End of file? */
return NULL; /* Yes --> Very bad, report error */
fputs(buf, dataout );
if (*buf == '\n') /* End of the header? */
return NULL; /* Yes --> Very bad, report error */
else if (equalni(received, buf, receivedlen))
hops++;
} while ( !equalni(&to[offset] , buf , tolen ));
token = strpbrk( buf ," \t");
/*--------------------------------------------------------------------*/
/* Proccess the rest of the addressees */
/*--------------------------------------------------------------------*/
cclen = strlen( &cc[offset] );
bcclen = strlen( &bcc[offset] );
do {
if (allocated == (*count+1)) /* Do we have room for addr? */
{
allocated += allocated / 2; /* Choose larger array size */
addrlist = realloc( addrlist ,
allocated * sizeof( *addrlist ));
checkref(addrlist); /* Verify the allocation worked */
} /* if */
ExtractAddress( address, token, FALSE ); /* Get address itself*/
if (!strlen(address))
{
printmsg(0,"Could not locate expected address in header");
*count = 0;
return NULL;
} /* if */
else {
addrlist[*count] = newstr( address );
/* Save permanent copy of address */
checkref( addrlist[*count] ); /* Verify strdup worked */
printmsg(4,"address[%d]= \"%s\"",*count, address);
*count += 1; /* Flag we got the address */
} /* else */
if (fgets( buf, BUFSIZ, datain ) == NULL) /* End of file? */
token = NULL; /* Yes --> Odd, but no major problem */
else if (*buf == '\n') /* End of the header? */
{
token = NULL; /* Yes --> Exit loop */
*header = FALSE; /* Report to caller the header is done */
blind = FALSE; /* Denote not a blind header */
}
else if (isspace(*buf)) /* Another address? */
token = buf; /* Yes --> Write it out */
else { /* No --> Determine what next header is*/
blind = FALSE; /* Assume not a blind header */
if (equalni(&cc[offset], buf, cclen)) /* Cc: header? */
token = strpbrk(buf," \t");
else if (equalni(&bcc[offset], buf, bcclen)) /* Bcc: header?*/
{
token = strpbrk(buf ," \t");
blind = TRUE;
} /* if */
else /* Unsupported header, exit loop */
token = NULL;
} /* else */
if ( ! blind )
fputs(buf, dataout );
} while (token != NULL );
/*--------------------------------------------------------------------*/
/* Return address list to caller */
/*--------------------------------------------------------------------*/
return addrlist;
} /* Parse822 */
/*--------------------------------------------------------------------*/
/* C o p y T e m p */
/* */
/* Copy the un-parsed parts of a message into the holding file */
/*--------------------------------------------------------------------*/
static boolean CopyTemp( void )
{
boolean header = TRUE;
char buf[BUFSIZ];
boolean newline = TRUE;
while (fgets(buf, BUFSIZ, datain) != NULL)
{
if (header)
{
if (*buf == '\n')
header = FALSE;
else if (equalni(received, buf, receivedlen))
hops++;
}
newline = buf[ strlen( buf ) - 1 ] == '\n';
if (fputs(buf, dataout) == EOF) /* I/O error? */
{
printerr(tempname);
printmsg(0,"I/O error on \"%s\"", tempname);
fclose(dataout);
return FALSE;
} /* if */
} /* while */
if (ferror(datain)) /* Clean end of file on input? */
{
printerr(namein);
Terminate(3);
}
if ( !newline ) /* Is the file terminated properly? */
{
printmsg(0, "rmail: Improperly formed message, adding final newline!");
fputc( '\n', dataout );
}
return header;
} /* CopyTemp */
/*--------------------------------------------------------------------*/
/* D a e m o n M a i l */
/* */
/* Send text in a mailbag file to address(es) specified by address */
/*--------------------------------------------------------------------*/
static boolean DaemonMail( const char *subject,
char **address,
int count )
{
char buf[BUFSIZ];
char *logname;
char *token;
char *moi = NULL;
struct UserTable *userp;
char *header = "To:";
char *cc = "Cc:";
boolean print = TRUE;
/*--------------------------------------------------------------------*/
/* Validate the input */
/*--------------------------------------------------------------------*/
if ( count == 0 )
{
printmsg(0,"rmail: No addresseses to deliver to!");
return FALSE;
}
/*--------------------------------------------------------------------*/
/* Determine our user id */
/*--------------------------------------------------------------------*/
logname = getenv( LOGNAME );
if ( logname == NULL )
logname = E_mailbox;
/*--------------------------------------------------------------------*/
/* Get the name of the user, or make one up */
/*--------------------------------------------------------------------*/
userp = checkuser(logname); /* Locate user id in host table */
if ( (userp != BADUSER) && (userp->realname != NULL) )
moi = userp->realname;
else if ( equali(logname, E_postmaster) || equali(logname, POSTMASTER))
moi = "Postmaster";
else if ( equali( logname, "uucp" ))
moi = "Unix to Unix Copy";
else
moi = logname; /* Dummy to ease formatting From: line */
/*--------------------------------------------------------------------*/
/* Add the boilerplate the front: */
/* */
/* Date, From, Organization, and Reply-To */
/*--------------------------------------------------------------------*/
fprintf(dataout,"%-10s by %s (%s %s);\n%-10s %s\n",
"Received:",E_domain,compilep, compilev,
" ", now );
/*--------------------------------------------------------------------*/
/* Generate a message-id */
/*--------------------------------------------------------------------*/
sprintf(buf, "<%lx.%s@%s>", time( NULL ) , E_nodename, E_domain);
PutHead("Message-ID:", buf, dataout , FALSE );
PutHead(NULL, NULL, dataout , FALSE );
PutHead("Date:", arpadate() , dataout, FALSE);
if (bflag[F_BANG])
sprintf(buf, "(%s) %s!%s", moi, E_nodename, logname );
else {
checkname( E_nodename ); /* Force loading of the E_fdomain name */
sprintf(buf, "\"%s\" <%s@%s>", moi, logname , E_fdomain );
}
PutHead("From:", buf, dataout, FALSE );
if (E_organization != NULL )
PutHead("Organization:", E_organization, dataout, FALSE);
/*--------------------------------------------------------------------*/
/* Write the address out */
/*--------------------------------------------------------------------*/
while( (count-- > 0) && print )
{
token = *address++;
if ( *token == '-') /* Option flag? */
{
if (token[1] == 'c')
{
header = cc;
cc = "";
}
else if (token[1] == 'b')
print = FALSE;
else
printmsg(0,"rmail: Invalid flag \"%s\" ignored!", token);
} /* if ( token == '-') */
else if ( print )
{
if (strpbrk(token,"!@") == nil(char))
{
if (bflag[F_BANG])
sprintf(buf, "%s!%s", E_nodename, token );
else
sprintf(buf, "%s@%s", token , E_fdomain );
token = buf;
}
PutHead(header , token, dataout, FALSE);
header = ""; /* Continue same field by default */
}
} /* while( (count-- > 0) && print ) */
/*--------------------------------------------------------------------*/
/* Handle the subject, if any */
/*--------------------------------------------------------------------*/
if (subject != NULL)
PutHead("Subject:", subject, dataout, FALSE);
PutHead(NULL, "", dataout, FALSE); /* Terminate the header line */
PutHead(NULL, "", dataout, FALSE); /* Terminate the header file */
/*--------------------------------------------------------------------*/
/* Return to caller */
/*--------------------------------------------------------------------*/
uuser = ruser = strncpy(fromuser, logname, sizeof fromuser);
/* Define user for UUCP From line */
fromuser[ sizeof fromuser - 1 ] = '\0';
rnode = bflag[F_BANG] ? E_nodename : E_fdomain;
/* Use full domain address, if possible */
strcpy(fromnode, E_nodename);/* Declare as local system */
return TRUE;
} /*DaemonMail*/
/*--------------------------------------------------------------------*/
/* P u t H e a d */
/* */
/* Write one line of an RFC-822 header */
/*--------------------------------------------------------------------*/
static void PutHead( const char *label,
const char *operand,
FILE *stream,
const boolean resent)
{
static boolean terminate = TRUE;
if (label == NULL ) /* Terminate call? */
{ /* Yes --> Reset Flag and return */
fputc('\n', stream); /* Terminate the current line */
terminate = TRUE;
return;
} /* if */
if (strlen(label)) /* First line of a header? */
{
if (!terminate) /* Terminate previous line? */
fputc('\n', stream);
if (resent)
fprintf(stream,"Resent-%s %s",label, operand);
else
fprintf(stream,"%-10s %s",label, operand);
terminate = FALSE; /* Flag that we did not end file */
} /* if */
else /* Continuing line */
fprintf(stream,",\n%-10s %s",label, operand);
} /* PutHead */
/*--------------------------------------------------------------------*/
/* u s a g e */
/* */
/* Report how the program works */
/*--------------------------------------------------------------------*/
static void usage( void )
{
static char syntax[] =
"Usage:\tRMAIL\t-t [-x debug] [-f | -F file]\n"
"\t\t-w [-x debug] [-f | -F file] [-s subject] addr1 [-c] addr2 [-b] addr3 ...\n"
"\t\t[-x debug] [-f | -F file] addr1 addr2 addr3 ...\n";
puts( syntax );
exit(3);
}